home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / hydrabbsa8 / source / src.lha / node / Node_Input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  55.8 KB  |  2,063 lines

  1. /*
  2.  
  3.   todo:
  4.  
  5.   * add history to Get_Line()
  6.   * add timeout to RunDoor()
  7.  
  8.   done:
  9.  
  10.   moved N_ND->DoorReturn[0]=0; from godoor() to systemdoor() and userdoor()
  11.   in case a door was supposed to run, but was not setup in the commands
  12.   files yet..
  13.  
  14.   moved N_ND->ActiveDoor=NULL; from rundoor to godoor() as CLI doors would
  15.   then cause the node to think the door had crashed :-)
  16.  
  17.  
  18. */
  19.  
  20. #define USE_BUILTIN_MATH
  21. #include <string.h>
  22. #include <math.h>
  23. #include <stdio.h>
  24. #include <exec/types.h>
  25. #include <libraries/locale.h>
  26. #include <exec/memory.h>
  27. #include <dos/dosextens.h>
  28. #include <intuition/screens.h>
  29. #include <intuition/intuition.h>
  30. #include <intuition/gadgetclass.h>
  31. #include <libraries/gadtools.h>
  32. #include <diskfont/diskfont.h>
  33. #include <utility/utility.h>
  34. #include <graphics/gfxbase.h>
  35. #include <devices/console.h>
  36. #include <workbench/workbench.h>
  37. #include <graphics/scale.h>
  38. #include <clib/locale_protos.h>
  39. #include <clib/exec_protos.h>
  40. #include <clib/wb_protos.h>
  41. #include <clib/intuition_protos.h>
  42. #include <clib/gadtools_protos.h>
  43. #include <clib/graphics_protos.h>
  44. #include <clib/utility_protos.h>
  45. #include <clib/diskfont_protos.h>
  46.  
  47. #include <dos/dos.h>
  48. #include <dos/dostags.h>
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include <time.h>
  53. #include <libraries/reqtools.h>
  54.  
  55. #include <clib/alib_protos.h>
  56. #include <clib/dos_protos.h>
  57. #include <clib/reqtools_protos.h>
  58.  
  59. #include "NodeGUI.h"
  60.  
  61. extern struct ReqToolsBase *ReqToolsBase;
  62. extern ULONG InfoWinActive;
  63. extern ULONG *rttags;
  64.  
  65. #include "/common/types.h"
  66. #include "/common/errors.h"
  67. #include "/common/defines.h"
  68. #include "/common/structures.h"
  69. #include "/common/strings.h"
  70. #include "/common/files.h"
  71. #include "/common/ansi_codes.h"
  72.  
  73. #include "Node_Console_Protos.h"
  74. #include "Node_Serial_Protos.h"
  75. #include "Node_Main_Protos.h"
  76. #include "Node_Misc_Protos.h"
  77. #include "Node_Input_Protos.h"
  78. #include "/library/hbbscommon_protos.h"
  79. #include "/library/hbbscommon_pragmas.h"
  80. #include "nodelibrary/hbbsnode_protos.h"
  81. #include "nodelibrary/hbbsnode_pragmas.h"
  82.  
  83. extern int N_NodeNum;
  84. extern struct BBSGlobalData *BBSGlobal;
  85. extern struct NodeData *N_ND;
  86. extern struct Library *HBBSCommonBase;
  87. extern struct Library *HBBSNodeBase;
  88. extern struct List *HistoryList;
  89. extern ULONG HistoryItems;
  90.  
  91. #include "/common/shared_protos.h"
  92.  
  93. void SetUpSigs( void )
  94. {
  95.   // this routine sets up all the signals availiable so you can checksignal() them
  96.   // or wait() on them or whatever....
  97.  
  98.  
  99.   if (N_ND->NodeSettings.Iconified==FALSE)
  100.     N_ND->WinSig=DEF_WINSIG;
  101.   else
  102.     N_ND->WinSig=0L;
  103.  
  104.   if (N_ND->InformationOpen)
  105.     N_ND->InfoWinSig=DEF_INFOWINSIG;
  106.   else
  107.     N_ND->InfoWinSig=0L;
  108.  
  109.   if (N_ND->SettingsOpen)
  110.     N_ND->SettingsWinSig=DEF_SETTINGSWINSIG;
  111.   else
  112.     N_ND->SettingsWinSig=0L;
  113.  
  114.   SetupConSerSigs();
  115.  
  116.   N_ND->PortSig=DEF_PORTSIG;
  117.   N_ND->TimerSig=DEF_TIMERSIG;
  118. }
  119.  
  120. void SetUpDoorSigs( void )
  121. {
  122.   // this routine sets up all the signals availiable so you can checksignal() them
  123.   // or wait() on them or whatever....
  124.  
  125.   if (N_ND->NodeSettings.Iconified==FALSE)
  126.     N_ND->WinSig=DEF_WINSIG;
  127.   else
  128.     N_ND->WinSig=0L;
  129.  
  130.   if (N_ND->InformationOpen)
  131.     N_ND->InfoWinSig=DEF_INFOWINSIG;
  132.   else
  133.     N_ND->InfoWinSig=0L;
  134.  
  135.   if (N_ND->SettingsOpen)
  136.     N_ND->SettingsWinSig=DEF_SETTINGSWINSIG;
  137.   else
  138.     N_ND->SettingsWinSig=0L;
  139.  
  140.   N_ND->PortSig=DEF_PORTSIG;
  141.   N_ND->TimerSig=DEF_TIMERSIG;
  142. }
  143.  
  144.  
  145. void HandleMiscSigs( ULONG ReturnedSigs )
  146. {
  147.   // this routine handles all stuff like the sysop clicking on the node window
  148.   // or closing the watch screen etc. etc...
  149.  
  150.   ULONG class;
  151.   UWORD code;
  152.   struct Gadget *pgsel;
  153.   struct IntuiMessage *imsg;
  154.  
  155.   if (ReturnedSigs & N_ND->WinSig)
  156.   {
  157.     while ((NodeWnd) && (imsg=GT_GetIMsg(NodeWnd->UserPort)))
  158.     {
  159.       class=imsg->Class;
  160.       code=imsg->Code;
  161.       pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
  162.       GT_ReplyIMsg(imsg);
  163.       ProcessWindowNodeWnd(class, code, pgsel);
  164.     }
  165.   }
  166.  
  167.   if (ReturnedSigs & N_ND->ConWinSig)
  168.   {
  169.     while ((N_ND->ConWin) && (imsg=GT_GetIMsg(N_ND->ConWin->UserPort)))
  170.     {
  171.       class=imsg->Class;
  172.       code=imsg->Code;
  173.       pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
  174.       GT_ReplyIMsg(imsg);
  175.       ProcessConWindow(class, code, pgsel);
  176.     }
  177.   }
  178.  
  179.   if (ReturnedSigs & N_ND->InfoWinSig)
  180.   {
  181.     while ((InfoWin) && (imsg=GT_GetIMsg(InfoWin->UserPort)))
  182.     {
  183.       class=imsg->Class;
  184.       code=imsg->Code;
  185.       pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
  186.       GT_ReplyIMsg(imsg);
  187.       ProcessWindowInfoWin(class, code, pgsel);
  188.     }
  189.   }
  190.  
  191.   if (ReturnedSigs & N_ND->SettingsWinSig)
  192.   {
  193.     while ((SettingsWin) && (imsg=GT_GetIMsg(SettingsWin->UserPort)))
  194.     {
  195.       class=imsg->Class;
  196.       code=imsg->Code;
  197.       pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
  198.       GT_ReplyIMsg(imsg);
  199.       ProcessWindowSettingsWin(class, code, pgsel);
  200.     }
  201.   }
  202.  
  203.   if (ReturnedSigs & N_ND->PortSig)
  204.   {
  205.     HandleMsg(); // node can only be closed by a message from the CONTROL program
  206.   }
  207.  
  208.   if (ReturnedSigs & (1L << N_ND->OLMPort->mp_SigBit))
  209.   {
  210.     struct Message *Msg;
  211.  
  212.     while (Msg=GetMsg(N_ND->OLMPort))
  213.     {
  214.       FreeVec(Msg);
  215.     }
  216.   }
  217. }
  218.  
  219. ULONG WaitAllSigs(void)
  220. {
  221.   return(Wait((1L << N_ND->OLMPort->mp_SigBit) | N_ND->SettingsWinSig | N_ND->InfoWinSig |N_ND->WinSig | N_ND->PortSig | N_ND->ConSig | N_ND->SerSig | N_ND->ConWinSig | N_ND->TimerSig));
  222. }
  223.  
  224.  
  225. #define KEY_NONE 0
  226. #define KEY_ESCAPE 1
  227. #define KEY_CSI 2
  228.  
  229. ULONG CheckCSI(UBYTE ch,ULONG wherefrom)
  230. {
  231.   ULONG ReturnedSigs;
  232.   BOOL done=FALSE;
  233.   int csipos=0;
  234. //  int loop;
  235.  
  236.   if ((N_ND->char1==27 && ch=='[') || (ch==155))
  237.   {
  238.  
  239.     N_ND->char1=0;
  240.     while (!done)
  241.     {
  242.       // now, we have to be specific as to where we think the control sequence
  243.       // is coming from, for instance, say you had got the first byte of the
  244.       // control sequence from the serial port, you obviously wouldn't want
  245.       // any more of the control sequence coming from the console.. :-)
  246.  
  247.       if (wherefrom==GET_SERIAL)
  248.       {
  249.         if (!N_ND->SerWaiting) SendSerReadData();
  250.       }
  251.       if (wherefrom==GET_CONSOLE)
  252.       {
  253.         if (!N_ND->ConWaiting && N_ND->ConOK) ConReadData(1); // we only want to do a char at a time...
  254.       }
  255.       SetUpSigs();
  256.       ReturnedSigs=WaitAllSigs();
  257.       // handlemiscsigs() MAY close the console window.. so be careful!
  258.       // also N_ND->RequestShutdown MIGHT get set if the sysop clicks close
  259.       // on the control panel, BUT if we are in the middle of an escape sequence
  260.       // we don't want to know.
  261.       HandleMiscSigs(ReturnedSigs);
  262.  
  263.       while ( ((wherefrom==GET_SERIAL) && HandleSerSigs(ReturnedSigs)) ||
  264.               ((wherefrom==GET_CONSOLE) && HandleConSigs(ReturnedSigs)) )
  265.       {
  266.         if ( N_ND->IBuffer[0]>=0x40 && N_ND->IBuffer[0] <=0x7E)
  267.         {
  268.           N_ND->csistring[csipos]=N_ND->IBuffer[0];
  269.           csipos++;
  270.           done=TRUE;
  271.         }
  272.         else
  273.         {
  274.           N_ND->csistring[csipos]=N_ND->IBuffer[0];
  275.           csipos++;
  276.         }
  277.       }
  278.     }
  279.     N_ND->csistring[csipos]=0; // null terminate str..
  280.  
  281.     // note: csipos is same as doing strlen(N_ND->csistring)..
  282.  
  283.     return(KEY_CSI);
  284.  
  285.   }
  286.   else
  287.   {
  288.     if (ch==27)
  289.     {
  290.       N_ND->char1=27;
  291.       return(KEY_NONE);
  292.     }
  293.   }
  294.  
  295.   if (N_ND->char1==27)
  296.   {
  297.     N_ND->char1=0;
  298.     return(KEY_ESCAPE);
  299.   }
  300.   return(KEY_NONE);
  301. }
  302.  
  303. void handleescape( void )
  304. {
  305. //  puts("Escape Pressed!");
  306. }
  307.  
  308. // when writing data to the console or serial port we MUST use <ESC>[ and not 0x9B
  309. // cos then only amiga's would understand it! :-)  But hey! what a cool idea!
  310.  
  311. /* NOT USED ANYMORE!  only getline used them and I've had to modify that too much!
  312.   void CursorLeft( short num )
  313.   {
  314.     UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
  315.     sprintf(outstr,"\033[%dD",num);
  316.     PutText(outstr);
  317.   }
  318.  
  319.   void CursorRight( short num )
  320.   {
  321.     UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
  322.     sprintf(outstr,"\033[%dC",num);
  323.     PutText(outstr);
  324.   }
  325.  
  326.   void DeleteChars( short num )
  327.   {
  328.     UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
  329.     sprintf(outstr,"\033[%dP",num);
  330.     PutText(outstr);
  331.   }
  332.  
  333.   void InsertChars( short num )
  334.   {
  335.     UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
  336.     sprintf(outstr,"\033[%d@",num);
  337.     PutText(outstr);
  338.   }
  339. */
  340.  
  341. ULONG CheckFunctionKeys( void )
  342. {
  343.   // this routine checks the function keys, and depending on the
  344.   // N_ND->LoginType it does certain things...
  345.  
  346.   ULONG status=IN_NOTHING;
  347.  
  348. //  puts(N_ND->csistring);
  349.  
  350.   if (stricmp(N_ND->csistring,str_CSI_F7)==0)
  351.   {
  352.     CleanupNodeConsoleWin();
  353.   }
  354.   else
  355.   if (stricmp(N_ND->csistring,str_CSI_F8)==0)
  356.   {
  357.     ChangeConsoleMode(2); // swap between screen and window..
  358.     if ((N_ND->LoginType==LOGIN_NONE) && (N_ND->CurrentLine[0]==0)) status=IN_DISPLAYAWAIT;
  359.   }
  360.   else
  361.   if (N_ND->LoginType==LOGIN_NONE)
  362.   {
  363.     if (stricmp(N_ND->csistring,str_CSI_F1)==0) status=IN_LOGIN;      // Local Login
  364.     if (stricmp(N_ND->csistring,str_CSI_F2)==0) InitModem();          // Init Modem
  365.     if (stricmp(N_ND->csistring,str_CSI_F3)==0) status=IN_IMMEDIATE;  // Answer Modem Now
  366.     if (stricmp(N_ND->csistring,str_CSI_F4)==0)
  367.     {
  368.       if (N_ND->CurrentLine[0]==0) status=IN_DISPLAYAWAIT;            // Display Awaitscreen if no chars recieved yet..
  369.     }
  370.     if (stricmp(N_ND->csistring,str_CSI_F5)==0)                       // toggle modem debug
  371.     {
  372.       N_ND->NodeDevice.ModemDebug=!N_ND->NodeDevice.ModemDebug;
  373.     }
  374.     if (stricmp(N_ND->csistring,str_CSI_F6)==0)
  375.     {
  376.       // we have to fool the system into thinking that there's someone
  377.       // logged in so that we can run the door! :-)
  378.       N_ND->LoginType=LOGIN_LOCAL;
  379.       N_ND->OnlineStatus=OS_ONLINE;
  380.  
  381.       GoSystemDoor("ACCOUNTEDIT",NULL);
  382.  
  383.       // but not forgetting to put it back to how it was..
  384.       N_ND->LoginType=LOGIN_NONE;
  385.       N_ND->OnlineStatus=OS_OFFLINE;
  386.  
  387.       // and display the await screen again to tidy up..
  388.       status=IN_DISPLAYAWAIT;
  389.     }
  390.     if (stricmp(N_ND->csistring,str_CSI_F9)==0) status=IN_TERMINAL;
  391.     if (stricmp(N_ND->csistring,str_CSI_F10)==0) status=IN_SHUTDOWN;
  392.   }
  393.   else // Oooh someone's logged in and the sysop wants to do something to the user!
  394.   {
  395.     if (stricmp(N_ND->csistring,str_CSI_F1)==0)
  396.     {
  397.       // chat door running ?
  398.       if ((N_ND->ActiveDoor) && (iposition("SYSOPCHAT",N_ND->ActiveDoor->node.ln_Name)>=0))
  399.       {
  400.         status=IN_ENDCHAT;
  401.       }
  402.       else
  403.       {
  404.         GoSystemDoor("SYSOPCHAT",NULL);
  405.       }
  406.     }
  407.     else
  408.     if (stricmp(N_ND->csistring,str_CSI_F6)==0)
  409.     {
  410.       if ((N_ND->ActiveDoor) && (iposition("ACCOUNTEDIT",N_ND->ActiveDoor->node.ln_Name)<0))
  411.       {
  412.         GoSystemDoor("ACCOUNTEDIT","SYSOPONLY");
  413.       }
  414.     }
  415.     else
  416.     if (stricmp(N_ND->csistring,str_CSI_SF6)==0)
  417.     {
  418.       if ((N_ND->ActiveDoor) && (iposition("ACCOUNTEDIT",N_ND->ActiveDoor->node.ln_Name)<0))
  419.       {
  420.         GoSystemDoor("ACCOUNTEDIT","SYSOPONLY CALLONLY");
  421.       }
  422.     }
  423.     else
  424.     if (stricmp(N_ND->csistring,str_CSI_SF10)==0)
  425.     {
  426.       if (N_ND->LoginType==LOGIN_REMOTE) HangUp();
  427.       return(IN_LOSSCARRIER);
  428.     }
  429.   }
  430.   return(status);
  431. }
  432. /*
  433.  
  434. #define GL_NONE      0  // default
  435. #define GL_HISTORY   1  // if set history is enabled (up/down cursor keys)
  436. #define GL_LINEWRAP  2  // if maxlen is reached then data back to the last ' ' character is copied to N_ND->CurrentLineWrap and returns immediately
  437. #define GL_IMMEDIATE 4  // returns when maxlen is reached
  438. #define GL_NORETURN  8  // does not print a cr+lf when a) reached maxlen or b) timeout or c) return press
  439. #define GL_EDIT      16 // enables cursor left/right and backspace/delete
  440. #define GL_DISPLAY   32 // display chars (don't specify for "Press [return] to contine" type prompts)
  441. #define GL_SYSOP     64 // does not write to, or read from, the serial port
  442. #define GL_USECHARS  128 // see N_ND->CharsAllowed
  443. #define GL_NOBEEP    256 // use with GL_USECHARS if you don't want a beep when
  444.                          // the presses a key not in N_ND->CharsAllowed
  445.  
  446. */
  447.  
  448. void ReDrawLine(ULONG Flags, int *xpos)
  449. {
  450.   char cmovestr[20];
  451.  
  452.   if (Flags & GL_DISPLAY)
  453.   {
  454.     // now move back to the start of the string and erase it,
  455.     // then print the new string
  456.  
  457.     if (*xpos)
  458.     {
  459.       sprintf(cmovestr,"\033[%dD",*xpos);
  460.     }
  461.     if (Flags & GL_SYSOP)
  462.     {
  463.       if (*xpos) PutConText(cmovestr);
  464.       PutConText("\033[K");
  465.       PutConText(N_ND->CurrentLine);
  466.     }
  467.     else
  468.     {
  469.       if (*xpos) PutText(cmovestr);
  470.       PutText("\033[K");
  471.       PutText(N_ND->CurrentLine);
  472.     }
  473.   }
  474.   *xpos=strlen(N_ND->CurrentLine);
  475. }
  476.  
  477.  
  478. ULONG Get_Line(ULONG Flags,char PasswordChar,ULONG MaxLen, ULONG Timeout, UBYTE *PromptStr)
  479. {
  480.   int editloop,editlen;
  481.   ULONG ReturnedSigs;
  482.   UBYTE CurrentChar[2]={0,0}; // 2 chars, use ¤tchar for null terminated string type..
  483.   int xpos=0;
  484.   ULONG csitype=0;
  485.   ULONG retval=IN_NOTHING; // this must NOT be returned to the caller!!!!!
  486.   struct TimerData *TD=NULL;
  487.   BOOL AddOK;
  488.   char *strptr;
  489.  
  490.   LONG HistoryNum=HistoryItems,OldHistNum=-1;
  491.   char cmovestr[20];
  492.  
  493.   if (N_ND->NodeFlags & NFLG_CTRLC) N_ND->NodeFlags-=NFLG_CTRLC;
  494.  
  495.  
  496.   N_ND->CurrentLine[0]=0; // null terminate the string..
  497.   N_ND->CurrentLineWrap[0]=0; // null terminate the string..
  498.  
  499.   if (Timeout)
  500.   {
  501.     TD=SubmitTimer(N_ND->NodeTimer,Timeout,0);
  502. //    if (TD) printf("Submitted a timer for %ld seconds\n",Timeout);
  503.   }
  504.  
  505.   if (PromptStr)
  506.   {
  507.     strNcpy(N_ND->CurrentLine,PromptStr,MaxLen > 0 ? MaxLen : LEN_CURRENTLINE);
  508.     if (Flags & GL_SYSOP)
  509.     {
  510.       PutConText(N_ND->CurrentLine);
  511.     }
  512.     else
  513.     {
  514.       PutText(N_ND->CurrentLine);
  515.     }
  516.     xpos=strlen(N_ND->CurrentLine);
  517.   }
  518.  
  519.   if (MaxLen==0) MaxLen=LEN_CURRENTLINE;
  520.  
  521.   if ((N_ND->LoginType==LOGIN_REMOTE) && (CarrierLost())) retval=IN_LOSSCARRIER;
  522.  
  523.   while (retval==IN_NOTHING)
  524.   {
  525.     // we only want to read the serial port if a) it's open and b) if we're
  526.     // still awaiting connect or someone is logged on..
  527.  
  528.     if (N_ND->SerOK && N_ND->LoginType !=LOGIN_LOCAL && (!(Flags & GL_SYSOP))  && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL)))
  529.     {
  530.       if (!N_ND->SerWaiting) SendSerReadData();
  531.     }
  532.  
  533.     // we ALWAYS want to read the console if the console window is open.
  534.     // cos the sysop might wanna do sommat!
  535.  
  536.     if (!N_ND->ConWaiting && N_ND->ConOK) ConReadData(1);
  537.  
  538.     SetUpSigs();
  539. //    if (Timeout)
  540. //    {
  541. //      printf("Timersig: %x\n",N_ND->TimerSig);
  542. //    }
  543.     ReturnedSigs=WaitAllSigs();
  544.     HandleMiscSigs(ReturnedSigs);
  545.  
  546.     // check olm's ?  *C* add an option/flag to NOT check for OLM's..
  547.     if ((!(N_ND->NodeFlags & NFLG_HANDLINGOLM)) && (!(Flags & GL_NOOLM)) && (ReturnedSigs & (1L << N_ND->OLMPort->mp_SigBit)) && (N_ND->NodeFlags & NFLG_OLMSWAITING))
  548.     {
  549.       GoSystemDoor("ReadOLM",NULL);
  550.  
  551.       xpos=0;
  552.       ReDrawLine(Flags,&xpos);
  553.     }
  554.  
  555.     if (Timeout)
  556.     {
  557.       if (TD)
  558.       {
  559.         if (CheckTimer(N_ND->NodeTimer,TD))
  560.         {
  561.           TD=NULL;
  562.           retval=IN_TIMEOUT;
  563.  
  564.           if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN))
  565.           {
  566.             if (Flags & GL_SYSOP)
  567.             {
  568.               PutConText("\r\n");
  569.             }
  570.             else
  571.             {
  572.               PutText("\r\n");
  573.             }
  574.           }
  575.  
  576. //          puts("Timeout!");
  577.         }
  578.       }
  579. //      else
  580. //      puts("Error, no timer data!");
  581.     }
  582.  
  583.     if (N_ND->RequestShutdown) retval=IN_SHUTDOWN;
  584.     if (N_ND->LoginType==LOGIN_REMOTE && CarrierLost()) retval=IN_LOSSCARRIER;
  585.  
  586.     while (retval==IN_NOTHING && HandleConSerSigs(ReturnedSigs)) // swapped!
  587.     {
  588.       // key press, restart timer!
  589.       if (Timeout)
  590.       {
  591. //        puts("restarting timer!");
  592.         if (TD) AbortTimer(N_ND->NodeTimer,TD);
  593.         TD=SubmitTimer(N_ND->NodeTimer,Timeout,0);
  594. //        if (TD) puts("restarted ok!");
  595.       }
  596.       // ok, we got some data from somehwere...
  597.  
  598.       CurrentChar[0]=N_ND->IBuffer[0];
  599.  
  600.       // checkcsi() needs to know EXACTLY where to look for incoming data
  601.  
  602.       csitype=CheckCSI(CurrentChar[0],ReturnedSigs & N_ND->ConSig ? GET_CONSOLE : GET_SERIAL);
  603.       switch (csitype)
  604.       {
  605.         case KEY_CSI:
  606.           {
  607.             if (Flags & GL_EDIT)
  608.             {
  609.               if (strcmp(N_ND->csistring,str_CSI_CURSORLEFT)==0)
  610.               {
  611.                 if (xpos>0)
  612.                 {
  613.                   xpos--;
  614.                   if (Flags & GL_DISPLAY)
  615.                   {
  616.                     if (Flags & GL_SYSOP)
  617.                     {
  618.                       PutConText("\033[1D");
  619.                     }
  620.                     else
  621.                     {
  622.                       PutText("\033[1D");
  623. //                      CursorLeft(1);
  624.                     }
  625.                   }
  626.                 }
  627.               }
  628.  
  629.               if (strcmp(N_ND->csistring,str_CSI_CURSORRIGHT)==0)
  630.               {
  631.                 if (xpos<strlen(N_ND->CurrentLine))
  632.                 {
  633.                   xpos++;
  634.                   if (Flags & GL_DISPLAY)
  635.                   {
  636.                     if (Flags & GL_SYSOP)
  637.                     {
  638.                       PutConText("\033[1C");
  639.                     }
  640.                     else
  641.                     {
  642.                       PutText("\033[1C");
  643. //                      CursorRight(1);
  644.                     }
  645.                   }
  646.                 }
  647.               }
  648.  
  649.               if ((Flags & GL_HISTORY) && (HistoryItems>0))
  650.               {
  651.                 if (strcmp(N_ND->csistring,str_CSI_CURSORUP)==0)
  652.                 {
  653.                   if (HistoryNum>0)
  654.                   {
  655.                     HistoryNum--;
  656.                   }
  657.                 }
  658.  
  659.                 if (strcmp(N_ND->csistring,str_CSI_CURSORDOWN)==0)
  660.                 {
  661.                   if (HistoryNum<HistoryItems)
  662.                   {
  663.                     HistoryNum++;
  664.                   }
  665.                 }
  666.  
  667.                 if (HistoryNum!=OldHistNum)
  668.                 {
  669.                   if (HistoryNum<HistoryItems)
  670.                   {
  671.                     strNcpy(N_ND->CurrentLine,HBBS_ListName(HistoryList,HistoryNum),MaxLen);
  672.                     OldHistNum=HistoryNum;
  673.                   }
  674.                   else
  675.                   {
  676.                     N_ND->CurrentLine[0]=0; // erase the line.. :-)
  677.                     HistoryNum=HistoryItems;
  678.                     OldHistNum=-1;
  679.                   }
  680.                   ReDrawLine(Flags,&xpos);
  681.                 }
  682.               }
  683.  
  684.             }
  685.             retval=CheckFunctionKeys();
  686.           }
  687.           break;
  688.         case KEY_ESCAPE:
  689.           handleescape();
  690.           // CheckCSI will leave one the character following the escape key
  691.           // in the buffer. so reset out mini string again..
  692.           CurrentChar[0]=N_ND->IBuffer[0];
  693.           // no break so we process the next char as well..
  694.         case KEY_NONE:
  695.           if (N_ND->LoginType!=LOGIN_NONE || ReturnedSigs & N_ND->SerSig)
  696.           {
  697.             if (CurrentChar[0]>=0x20) // i.e. not unprintable or a control char..
  698.             {
  699.               if (CurrentChar[0]==127) // DEL
  700.               {
  701.                 if (Flags & GL_EDIT)
  702.                 {
  703.                   editlen=strlen(N_ND->CurrentLine);
  704.                   if (xpos!=editlen)
  705.                   {
  706.                     for (editloop=xpos;editloop<(min(editlen,MaxLen));editloop++) // <= to copy the null terminator as well!
  707.                     {
  708.                       N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop+1];
  709.                     }
  710.                     if (Flags & GL_DISPLAY)
  711.                     {
  712.                       if (Flags & GL_SYSOP)
  713.                       {
  714.                         PutConText("\033[1P");
  715.                       }
  716.                       else
  717.                       {
  718.                         PutText("\033[1P");
  719. //                        DeleteChars(1);
  720.                       }
  721.                     }
  722.                   }
  723.                 }
  724.               }
  725.               else
  726.               {
  727.                 AddOK=FALSE;
  728.                 if (Flags & GL_USECHARS)
  729.                 {
  730.                   if (strchr(N_ND->CharsAllowed,CurrentChar[0]))
  731.                   {
  732.                     AddOK=TRUE;
  733.                   }
  734.                   else
  735.                   {
  736.                     // ooh, wrong char, lets do a beep..
  737.                     if (!(Flags & GL_NOBEEP))
  738.                     {
  739.                       // but only if we're allowed to!
  740.                       if (Flags & GL_SYSOP)
  741.                       {
  742.                         PutConChar(7); // 7 = BEEP char!
  743.                       }
  744.                       else
  745.                       {
  746.                         PutChar(7);
  747.                       }
  748.                     }
  749.                   }
  750.                 } else AddOK=TRUE;
  751.                 if (AddOK)
  752.                 {
  753.                   // ok, no function key pressed, so add the char to the end of the string...
  754.                   if ((editlen=strlen(N_ND->CurrentLine)) < min(LEN_CURRENTLINE,MaxLen))
  755.                   {
  756.                     if (xpos==editlen) // tag char on end ?
  757.                     {
  758.                       xpos++;
  759.                       strcat(N_ND->CurrentLine,CurrentChar);
  760.                       if (Flags & GL_DISPLAY)
  761.                       {
  762.                         if (Flags & GL_SYSOP)
  763.                         {
  764.                           if (PasswordChar) PutConChar(PasswordChar); else PutConChar(CurrentChar[0]);
  765.                         }
  766.                         else
  767.                         {
  768.                           if (PasswordChar) PutChar(PasswordChar); else PutChar(CurrentChar[0]);
  769.                         }
  770.                       }
  771.                     }
  772.                     else
  773.                     {
  774.                       if (Flags & GL_EDIT)
  775.                       {
  776.                         // gotta insert char!
  777.                         for (editloop=editlen+1; editloop>xpos ;editloop--) //+1 for null terminator
  778.                         {
  779.                           N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop-1];
  780.                         }
  781.                         N_ND->CurrentLine[xpos]=CurrentChar[0];
  782.                         if (Flags & GL_DISPLAY)
  783.                         {
  784.                           if (Flags & GL_SYSOP)
  785.                           {
  786.                             PutConText("\033[1@");
  787.                             PutConChar(CurrentChar[0]);
  788.                           }
  789.                           else
  790.                           {
  791.                             PutText("\033[1@");
  792.                             PutChar(CurrentChar[0]);
  793.                           }
  794.                         }
  795.                         xpos++;
  796.                       }
  797.                     }
  798.                   }
  799.                 }
  800.               }
  801.             }
  802.             else
  803.             {
  804.               switch (CurrentChar[0])
  805.               {
  806.                 case 13: // return
  807.                   if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN)) PutText(str_CRLF); // linefeed...
  808.                   retval=IN_GOTLINE;
  809.                   break;
  810.  
  811.                 case 27: //escape
  812.                   handleescape();
  813.                   break;
  814.  
  815.                 case 3: //ctrl+c
  816.                   if (!(N_ND->NodeFlags & NFLG_CTRLC)) N_ND->NodeFlags+=NFLG_CTRLC;
  817.                   break;
  818.                 case 24: //ctrl+x, clear the line..
  819.                   N_ND->CurrentLine[0]=0;
  820.                   ReDrawLine(Flags,&xpos);
  821.                   break;
  822.  
  823.                 case 8: //backspace
  824.                   if (Flags & GL_EDIT)
  825.                   {
  826.                     if (xpos>0)
  827.                     {
  828.                       xpos--;
  829.                       editlen=strlen(N_ND->CurrentLine);
  830.                       for (editloop=xpos;editloop<editlen;editloop++) // <= to copy the null terminator as well!
  831.                       {
  832.                         N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop+1];
  833.                       }
  834.                       if (Flags & GL_DISPLAY)
  835.                       {
  836.                         if (Flags & GL_SYSOP)
  837.                         {
  838.                           PutConText("\033[1D\033[1P");
  839.                         }
  840.                         else
  841.                         {
  842.                           PutText("\033[1D\033[1P");
  843. //                          CursorLeft(1);
  844. //                          DeleteChars(1);
  845.                         }
  846.                       }
  847.                     }
  848.                   }
  849.                   break;
  850.               }
  851.             }
  852.           }
  853.           break;
  854.       }
  855.     }
  856.     if (retval==IN_NOTHING)
  857.     {
  858.       if ((strlen(N_ND->CurrentLine)==MaxLen) && (Flags & GL_IMMEDIATE))
  859.       {
  860.         retval=IN_GOTLINE;
  861.  
  862.         if (Flags & GL_LINEWRAP)
  863.         {
  864.           if (strptr=strrchr(N_ND->CurrentLine,' '))
  865.           {
  866.             if (Flags & GL_DISPLAY)
  867.             {
  868.               sprintf(cmovestr,"\033[%dD\033[K",strlen(N_ND->CurrentLine)-(strptr-N_ND->CurrentLine));
  869.               if (Flags & GL_SYSOP)
  870.               {
  871.                 PutConText(cmovestr);
  872.               }
  873.               else
  874.               {
  875.                 PutText(cmovestr);
  876.               }
  877.             }
  878.  
  879.             strcpy(N_ND->CurrentLineWrap,strptr+1);
  880.             *strptr=0;
  881.  
  882.             // *C* update the display!
  883.           }
  884.         }
  885.  
  886.  
  887.         if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN)) PutText(str_CRLF); // linefeed...
  888.       }
  889.     }
  890.   };
  891.   if (TD) AbortTimer(N_ND->NodeTimer,TD);
  892.  
  893.  
  894.   if (Flags & GL_HISTORY)
  895.   {
  896.     if (N_ND->CurrentLine[0])
  897.     {
  898.       if (!NewStrNode(N_ND->CurrentLine,HistoryList))
  899.       {
  900.         HistoryItems++;
  901.       }
  902.     }
  903.   }
  904.  
  905.  
  906.   if (retval==IN_LOSSCARRIER)
  907.   {
  908.     N_ND->OnlineStatus=OS_OFFLINE;
  909.     if (Flags & GL_DISPLAY) PutConText(str_CRLF);
  910.   }
  911.   return(retval);
  912. }
  913.  
  914. void RunDoor(char *doorname,char *options,BOOL DebugMode,BOOL ASync)
  915. {
  916.   // function to start a door
  917.   // *C* have timeout on door, check file exists before attempting to run it...
  918.  
  919.   char cmd[BIG_STR];
  920.  
  921.   sprintf(cmd,"%s %d %s",doorname,N_NodeNum,options ? options : "\0");
  922.   if (DebugMode)
  923.   {
  924.  
  925.     printf("DOOR DEBUG MODE ON - Start the door with the settings below!\n"
  926.            "==============================================================================\n"
  927.            "%s\n"
  928.            "==============================================================================\n",cmd);
  929.   }
  930.   else
  931.   {
  932.     HBBS_RunDOSCMD(cmd,ASync);
  933.   }
  934. }
  935.  
  936. struct MsgPort* CreateDoorStartPort( void )
  937. {
  938.   struct MsgPort *DP=NULL;
  939.   sprintf(N_ND->DoorStartPortName,"DoorStart_N%d_D%d",N_ND->NodeNum,N_ND->DoorsRunning+1);
  940.   DP=CreatePort(N_ND->DoorStartPortName,0);
  941.   return(DP);
  942. }
  943.  
  944. BOOL CheckDoorStarted(struct MsgPort *DP,char *systemoptions)
  945. {
  946.   struct DoorActivityMsg *DM;
  947.   BOOL retval=FALSE;
  948.  
  949.   while (DM=(struct DoorActivityMsg *)GetMsg(DP))
  950.   {
  951.     N_ND->ActiveDoor->SystemOptions=systemoptions;
  952.     ReplyMsg((struct Message *)DM);
  953.     retval=TRUE;
  954.   }
  955.   return(retval);
  956. }
  957.  
  958. void GoDoor(char *doorname,char *systemoptions,char *options,BOOL DebugMode)
  959. {
  960.   char outstr[256];
  961.   ULONG ReturnedSigs;
  962.   struct DoorData *CurrentDoor;
  963.   struct TimerData *TD;
  964.   BOOL timeout,doorstarted;
  965.   struct MsgPort *DP;
  966.   char *clinesave=N_ND->CurrentLine; // save old line..
  967.  
  968.   if (PathOK(doorname)) // does door exist ?
  969.   {
  970. //    strcpy(N_ND->Action,"Loading Door!");
  971. //    DOOR_UpdateNodeStatus(UPD_ACTION);
  972.  
  973.     if (N_ND->CurrentLine=AllocVec(LEN_CURRENTLINE,MEMF_PUBLIC))
  974.     {
  975.       N_ND->CurrentLine[0]=0;
  976.  
  977.                                             //*C* uncomment! make it a sysop definable setting ?
  978.       if (TD=SubmitTimer(N_ND->NodeTimer,300/*TIMEOUT_DOORLOAD*/,0))
  979.       {
  980.         timeout=FALSE;
  981.         doorstarted=FALSE;
  982.  
  983.         if (DP=CreateDoorStartPort())
  984.         {
  985.           N_ND->ActiveDoor=NULL;
  986.           RunDoor(doorname,options,DebugMode,TRUE);
  987.  
  988. //        strcpy(N_ND->Action,"Waiting For Door");
  989. //        DOOR_UpdateNodeStatus(UPD_ACTION);
  990.  
  991.           do
  992.           {
  993.             Wait (1L<<DP->mp_SigBit | DEF_PORTSIG );
  994.             doorstarted=CheckDoorStarted(DP,systemoptions);
  995.             if (timeout=CheckTimer(N_ND->NodeTimer,TD))
  996.             {
  997.               TD=NULL;
  998.             }
  999.           } while(doorstarted==FALSE && timeout==FALSE);
  1000.  
  1001.           DeletePort(DP);
  1002.  
  1003.           if (timeout)
  1004.           {
  1005.             HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_DOORTIMEOUT,doorname,TYPE_WARNING);
  1006.           }
  1007.           else
  1008.           {
  1009.             if (TD) AbortTimer(N_ND->NodeTimer,TD);
  1010.  
  1011.             strNcpy(N_ND->Action,N_ND->ActiveDoor->node.ln_Name,MAX_ACTION_LEN);
  1012.             DOOR_UpdateNodeStatus(UPD_ACTION);
  1013.  
  1014.             if (N_ND->ActiveDoor!=NULL)
  1015.             {
  1016.               // wait until the door stops!
  1017.  
  1018.               CurrentDoor=N_ND->ActiveDoor;
  1019.               do
  1020.               {
  1021.                 SetUpDoorSigs();
  1022.                 ReturnedSigs=Wait(N_ND->ConWinSig |
  1023.                                   N_ND->SettingsWinSig |
  1024.                                   N_ND->InfoWinSig |
  1025.                                   N_ND->WinSig |
  1026.                                   N_ND->PortSig);
  1027.  
  1028.                 HandleMiscSigs(ReturnedSigs);
  1029.  
  1030.                 // while the door is started we should check for function key presses
  1031.                 // and so on... (which is handled by HandleDoorMsg())
  1032.  
  1033.  
  1034.                 // repeat wait loop until the door is finished, can detect by looking to see
  1035.                 // what the value of the door pointer is when it starts, and then keep comparing
  1036.                 // that to the the ActiveDoor pointer, if they differ the door has closed (as
  1037.                 // the ActiveDoor Pointer would point to a different door or to NULL...
  1038.               } while (N_ND->ActiveDoor==CurrentDoor);
  1039.               if (DebugMode) puts(N_ND->DoorReturn);
  1040.             }
  1041.           }
  1042.         }
  1043.         else
  1044.         {
  1045.           if (TD) AbortTimer(N_ND->NodeTimer,TD);
  1046.         }
  1047.       }
  1048.       FreeVec(N_ND->CurrentLine);
  1049.       N_ND->CurrentLine=clinesave;
  1050.     }
  1051.   }
  1052.   else
  1053.   {
  1054.     sprintf(outstr,"The door file (%s) is missing!\r\n",doorname);
  1055.     PutText(outstr);
  1056.     HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
  1057.   }
  1058.   if (N_ND->ActiveDoor)
  1059.   {
  1060.     strNcpy(N_ND->Action,N_ND->ActiveDoor->node.ln_Name,MAX_ACTION_LEN);
  1061.     DOOR_UpdateNodeStatus(UPD_ACTION);
  1062.   }
  1063. }
  1064.  
  1065. void PrintList( struct List *list)
  1066. {
  1067.   struct Node *node;
  1068.   for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
  1069.   {
  1070.     puts(node->ln_Name);
  1071.   }
  1072. }
  1073.  
  1074. void CheckDoorTypes(char *actualtype,struct Node *node)
  1075. {
  1076.   if (stricmp(actualtype,"SCREEN")==0)
  1077.   {
  1078.     DisplayScreen(node->ln_Name);
  1079.   }
  1080.   else
  1081.   {
  1082.     if (stricmp(actualtype,"SSCREEN")==0)
  1083.     {
  1084.       DisplaySpecialScreen(node->ln_Name);
  1085.     }
  1086.     else
  1087.     {
  1088.       if (stricmp(actualtype,"CLS")==0)
  1089.       {
  1090.         PutText(ANSI_CLS);
  1091.       }
  1092.       else
  1093.       {
  1094.         if (stricmp(actualtype,"PAUSE")==0)
  1095.         {
  1096.           PausePrompt(node->ln_Name,0);
  1097.         }
  1098.         else
  1099.         {
  1100.           if (stricmp(actualtype,"ECHO")==0)
  1101.           {
  1102.             PutText(node->ln_Name);
  1103.             PutText("\r\n");
  1104.           }
  1105.           else
  1106.           {
  1107.             if (stricmp(actualtype,"DOS")==0)
  1108.             {
  1109.               HBBS_RunDOSCMD(node->ln_Name,FALSE);
  1110.             }
  1111.           }
  1112.         }
  1113.       }
  1114.     }
  1115.   }
  1116. }
  1117.  
  1118. #define GOSYS_CONF 1
  1119. #define GOSYS_NODE 2
  1120. #define GOSYS_CMDS 3
  1121.  
  1122. V_BOOL GoSystemDoor( char *doorname, char *options )
  1123. {
  1124.   /* must search the SYSTEM door list in the commands dir for first the conf,
  1125.   then the node and finally the hbbs:commands directories.. when it finds
  1126.   it it runs it, note that there may be more than one door to call at a time
  1127.   as you may define more than one door for each system function. e.g.
  1128.  
  1129.   Examine_Type_1=NORMAL
  1130.   Examine_DOOR_1=HBBS:Doors/User/Examine/Examine.HBBS
  1131.   Examine_Param_1=
  1132.  
  1133.   Examine_Type_2=NORMAL
  1134.   Examine_DOOR_2=HBBS:Doors/User/DIZTimeAdd/DIZTimeAdd.HBBS
  1135.   Examine_Param_2=[=- Uploaded At HH:MM -=]
  1136.  
  1137.   Examine_Type_3=NORMAL
  1138.   Examine_DOOR_3=HBBS:Doors/User/Sentby/Sentby.HBBS
  1139.   Examine_Param_3=Sent,Cps,Node
  1140.  
  1141.   note: if you have say Examine_Type_1 in hbbs:conferences/newuser/commands/system
  1142.   and in hbbs:commands/system the set of commands in hbbs:commands/system WILL NOT
  1143.   be run as the former file has priority over the latter.
  1144.  
  1145.   */
  1146.  
  1147.   UBYTE filename[BIG_STR],*optionname,*actualparam=NULL,*actualtype=NULL;
  1148.   V_BOOL done=FALSE,DebugMode;
  1149.   short whichfile;
  1150.   struct CfgFileData *CfgFile;
  1151.   struct List *CmdList=NULL;
  1152.   struct Node *node;
  1153.   short doornum;
  1154.  
  1155.   N_ND->DoorReturn[0]=0; // null terminate string...
  1156.   N_ND->DoorContinue=TRUE;
  1157.  
  1158.   for (whichfile=GOSYS_CONF;whichfile<=GOSYS_CMDS && !done;whichfile++)
  1159.   {
  1160.     if (stricmp("AWAIT",doorname)!=0 && stricmp("ACCOUNTEDIT",doorname)!=0 && N_ND->OnlineStatus==OS_OFFLINE)
  1161.     {
  1162.       done=TRUE;
  1163.     }
  1164.     else
  1165.     {
  1166.       filename[0]=0;
  1167.       switch(whichfile)
  1168.       {
  1169.         case GOSYS_CONF:
  1170.           if (N_ND->CurrentConf) // have we joined a conf yet ?
  1171.           {
  1172.             strcpy(filename,N_ND->CurrentConf->ConfPath);
  1173.             strcat(filename,FILENAME_CMDSSYSTEM);
  1174.           }
  1175.           break;
  1176.         case GOSYS_NODE:
  1177.           strcpy(filename,N_ND->NodeLocation);
  1178.           strcat(filename,FILENAME_CMDSSYSTEM);
  1179.           break;
  1180.         case GOSYS_CMDS:
  1181.           strcpy(filename,FILE_HBBS);
  1182.           strcat(filename,FILENAME_CMDSSYSTEM);
  1183.           break;
  1184.       }
  1185.       if (filename[0]) // string present ?
  1186.       {
  1187.         if (optionname=AllocVec(strlen(doorname)+10,MEMF_PUBLIC))
  1188.         {
  1189.           strcpy(optionname,doorname);
  1190.           strcat(optionname,"_Door");
  1191.           if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
  1192.           {
  1193.             if (HBBS_GetSetting(CfgFile,(void *)&CmdList,VTYPE_STRINGLIST,optionname,OPT_MULTI))
  1194.             {
  1195.               for (doornum=1,node = CmdList->lh_Head ; N_ND->DoorContinue && node->ln_Succ ; node =node->ln_Succ,doornum++)
  1196.               {
  1197.                 actualtype=NULL;
  1198.                 sprintf(optionname,"%s_Type_%d",doorname,doornum);
  1199.                 if (HBBS_GetSetting(CfgFile,(void *)&actualtype,VTYPE_STRING,optionname,OPT_SINGLE))
  1200.                 {
  1201.                   actualparam=NULL;
  1202.                   sprintf(optionname,"%s_Param_%d",doorname,doornum);
  1203.                   HBBS_GetSetting(CfgFile,(void *)&actualparam,VTYPE_STRING,optionname,OPT_SINGLE);
  1204.                   if (!actualparam) actualparam=DupStr("");
  1205.                   if (actualparam)
  1206.                   {
  1207.                     done=TRUE;
  1208.  
  1209.                     DebugMode=FALSE;
  1210.  
  1211.                     sprintf(optionname,"%s_Debug_%d",doorname,doornum);
  1212.                     HBBS_GetSetting(CfgFile,(void *)&DebugMode,VTYPE_BOOL,optionname,OPT_SINGLE);
  1213.  
  1214.                     if (stricmp(actualtype,"NORMAL")==0)
  1215.                     {
  1216.                       GoDoor(node->ln_Name,actualparam,options,DebugMode);
  1217.                     }
  1218.                     else
  1219.                     {
  1220.                       if (stricmp(actualtype,"CLI")==0)
  1221.                       {
  1222.                         RunDoor(node->ln_Name,options,DebugMode,FALSE);
  1223.                       }
  1224.                       else
  1225.                       {
  1226.                         CheckDoorTypes(actualtype,node);
  1227.                       }
  1228.                     }
  1229.                     FreeStr(actualparam);
  1230.                   }
  1231.                   FreeStr(actualtype);
  1232.                 }
  1233.               }
  1234.               FreeStrList(CmdList);
  1235.             }
  1236.             HBBS_FlushConfig(CfgFile);
  1237.           }
  1238.           FreeVec(optionname);
  1239.         }
  1240.       }
  1241.     }
  1242.   }
  1243.   return(done);
  1244. }
  1245.  
  1246. short WhatAccessNode(V_SMALLNUM accesslevel)
  1247. {
  1248.   short retval=-1;
  1249.   char tmpstr[10];
  1250.   short loop;
  1251.   struct Node *node;
  1252.  
  1253.  
  1254.   sprintf(tmpstr,"%d",accesslevel);
  1255.  
  1256.   for (loop=0,node = BBSGlobal->AcsLevelList->lh_Head ; node->ln_Succ && retval==-1 ; node =node->ln_Succ,loop++)
  1257.   {
  1258.     if (strcmp(tmpstr,node->ln_Name)==0)
  1259.     {
  1260.       retval=loop;
  1261.     }
  1262.   }
  1263.   return(retval);
  1264. }
  1265.  
  1266. #define GOUSER_CONF 1
  1267. #define GOUSER_NODE 2
  1268. #define GOUSER_CMDS 3
  1269.  
  1270.  
  1271. V_BOOL GoUserDoor( char *doorname, char *options )
  1272. {
  1273.  
  1274.   /* this door must first determine the current access level, then scan the following
  1275.      files to find out what door to run.
  1276.  
  1277.      CurrentConf/Commands/Level_XX
  1278.      CurrentConf/Commands/AllLevels
  1279.      Currentnode/Commands/Level_XX
  1280.      Currentnode/Commands/AllLevels
  1281.      HBBS:Commnds/Level_XX
  1282.      HBBS:Commnds/AllLevels
  1283.  
  1284.      then when it finds the door to run it calls it up!
  1285.  
  1286.   */
  1287.  
  1288.   UBYTE dirname[BIG_STR],filename[BIG_STR],*optionname,*actualparam=NULL,*actualtype=NULL;
  1289.   V_BOOL done=FALSE,DebugMode,SearchedAll;
  1290.   short whichfile;
  1291.   struct CfgFileData *CfgFile;
  1292.   struct List *CmdList=NULL;
  1293.   struct Node *node;
  1294.   short doornum,CurrentAccess;
  1295.  
  1296.   N_ND->DoorReturn[0]=0; // null terminate string...
  1297.   N_ND->DoorContinue=TRUE;
  1298.  
  1299.   for (whichfile=GOUSER_CONF;whichfile<=GOUSER_CMDS && !done;whichfile++)
  1300.   {
  1301.     dirname[0]=0;
  1302.     filename[0]=0;
  1303.     switch(whichfile)
  1304.     {
  1305.       case GOUSER_CONF:
  1306.         if (N_ND->CurrentConf) // have we joined a conf yet ?
  1307.         {
  1308.           sprintf(dirname,"%sCommands/",N_ND->CurrentConf->ConfPath);
  1309.         }
  1310.         break;
  1311.       case GOUSER_NODE:
  1312.         sprintf(dirname,"%sCommands/",N_ND->NodeLocation);
  1313.         break;
  1314.       case GOUSER_CMDS:
  1315.         strcpy(dirname,"HBBS:Commands/");
  1316.         break;
  1317.     }
  1318.     if (dirname[0]) // string present ? cos it might not be if we ain't in a conf..
  1319.     {
  1320.       // ok, no we know where to look for the commands, so we gotta check
  1321.       // "Level_<access>" downto "Level_00" until we find it, if it ain't there then
  1322.       // we have to check "All_Levels"
  1323.  
  1324.       SearchedAll=FALSE;
  1325.       CurrentAccess=WhatAccessNode(N_ND->User.CallData.Access);
  1326.  
  1327.       do
  1328.       {
  1329.         if (CurrentAccess<0)
  1330.         {
  1331.           sprintf(filename,"%sAll_Levels",dirname);
  1332.           SearchedAll=TRUE;
  1333.         }
  1334.         else
  1335.         {
  1336.           node=GetNode(BBSGlobal->AcsLevelList,CurrentAccess);
  1337.  
  1338.           sprintf(filename,"%sLevel_%s",dirname,node->ln_Name);
  1339.         }
  1340.  
  1341.         if (optionname=AllocVec(strlen(doorname)+10,MEMF_PUBLIC))
  1342.         {
  1343.           sprintf(optionname,"%s_Door",doorname);
  1344.           if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
  1345.           {
  1346.             if (HBBS_GetSetting(CfgFile,(void *)&CmdList,VTYPE_STRINGLIST,optionname,OPT_MULTI))
  1347.             {
  1348.               for (doornum=1,node = CmdList->lh_Head ; N_ND->DoorContinue && node->ln_Succ ; node =node->ln_Succ,doornum++)
  1349.               {
  1350.                 actualtype=NULL;
  1351.                 sprintf(optionname,"%s_Type_%d",doorname,doornum);
  1352.                 if (HBBS_GetSetting(CfgFile,(void *)&actualtype,VTYPE_STRING,optionname,OPT_SINGLE))
  1353.                 {
  1354.                   actualparam=NULL;
  1355.                   sprintf(optionname,"%s_Param_%d",doorname,doornum);
  1356.                   HBBS_GetSetting(CfgFile,(void *)&actualparam,VTYPE_STRING,optionname,OPT_SINGLE);
  1357.                   if (!actualparam) actualparam=DupStr("");
  1358.                   if (actualparam)
  1359.                   {
  1360.                     DebugMode=FALSE;
  1361.                     if (stricmp(actualtype,"NORMAL")==0)
  1362.                     {
  1363.                       sprintf(optionname,"%s_Debug_%d",doorname,doornum);
  1364.                       HBBS_GetSetting(CfgFile,(void *)&DebugMode,VTYPE_BOOL,optionname,OPT_SINGLE);
  1365.  
  1366.                       GoDoor(node->ln_Name,actualparam,options,DebugMode);
  1367.                     }
  1368.                     else
  1369.                     {
  1370.                       if (stricmp(actualtype,"CLI")==0)
  1371.                       {
  1372.                         RunDoor(node->ln_Name,options,DebugMode,FALSE);
  1373.                       }
  1374.                       else
  1375.                       {
  1376.                         CheckDoorTypes(actualtype,node);
  1377.                       }
  1378.                     }
  1379.                     FreeStr(actualparam);
  1380.                   }
  1381.                   FreeStr(actualtype);
  1382.                 }
  1383.               }
  1384.               FreeStrList(CmdList);
  1385.               done=TRUE;
  1386.             }
  1387.             HBBS_FlushConfig(CfgFile);
  1388.           }
  1389.           FreeVec(optionname);
  1390.         }
  1391.         CurrentAccess--;
  1392.  
  1393.       } while (!( done || SearchedAll));
  1394.  
  1395.     }
  1396.   }
  1397.   return(done);
  1398. }
  1399.  
  1400. // *M* Move routines into HBBSNode.C
  1401.  
  1402. void Add_Last_Caller(char *data)
  1403. {
  1404.   struct Node *node;
  1405.  
  1406.   if (N_ND->Current_Last_Callers==N_ND->Max_Last_Callers)
  1407.   {
  1408.     node=RemTail(N_ND->Last_Callers);
  1409.     FreeStr(node->ln_Name);
  1410.     FreeVec(node);
  1411.     N_ND->Current_Last_Callers--;
  1412.   }
  1413.   if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
  1414.   {
  1415.     node->ln_Name=DupStr(data);
  1416.     AddHead(N_ND->Last_Callers,node);
  1417.     N_ND->Current_Last_Callers++;
  1418.   }
  1419.   UpdateInfoWin();
  1420.   SendRequest(REQ_UPDATEINFO);
  1421. }
  1422.  
  1423. void Add_Last_PWFail(char *data)
  1424. {
  1425.   struct Node *node;
  1426.  
  1427.   if (N_ND->Current_Last_PWFails==N_ND->Max_Last_PWFails)
  1428.   {
  1429.     node=RemTail(N_ND->Last_PWFails);
  1430.     FreeStr(node->ln_Name);
  1431.     FreeVec(node);
  1432.     N_ND->Current_Last_PWFails--;
  1433.   }
  1434.   if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
  1435.   {
  1436.     node->ln_Name=DupStr(data);
  1437.     AddHead(N_ND->Last_PWFails,node);
  1438.     N_ND->Current_Last_PWFails++;
  1439.   }
  1440.   UpdateInfoWin();
  1441.   SendRequest(REQ_UPDATEINFO);
  1442. }
  1443.  
  1444. void Add_Last_Upload(char *data)
  1445. {
  1446.   struct Node *node;
  1447.  
  1448.   if (N_ND->Current_Last_Uploads==N_ND->Max_Last_Uploads)
  1449.   {
  1450.     node=RemTail(N_ND->Last_Uploads);
  1451.     FreeStr(node->ln_Name);
  1452.     FreeVec(node);
  1453.     N_ND->Current_Last_Uploads--;
  1454.   }
  1455.   if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
  1456.   {
  1457.     node->ln_Name=DupStr(data);
  1458.     AddHead(N_ND->Last_Uploads,node);
  1459.     N_ND->Current_Last_Uploads++;
  1460.   }
  1461.   UpdateInfoWin();
  1462.   SendRequest(REQ_UPDATEINFO);
  1463. }
  1464.  
  1465.  
  1466. #define DSS_CONF 1
  1467. #define DSS_NODE 2
  1468. #define DSS_HBBS 3
  1469. #define DSS_ERR  4
  1470.  
  1471. V_BOOL DisplaySpecialScreen(char *ScreenName)
  1472. {
  1473.   char filename[BIG_STR];
  1474.   BOOL TriedAllLevels,Done=FALSE;
  1475.   struct Node *node;
  1476.  
  1477.   short whichdir=DSS_CONF;
  1478.   short CurrentAccess;
  1479.  
  1480.   do
  1481.   {
  1482.     filename[0]=0;
  1483.     if (N_ND->User.Valid)
  1484.     {
  1485.       TriedAllLevels=FALSE;
  1486.       CurrentAccess=WhatAccessNode(N_ND->User.NormalData.Access);
  1487.     }
  1488.     else
  1489.     {
  1490.       CurrentAccess=-1;
  1491.     }
  1492.  
  1493.     do
  1494.     {
  1495.       switch(whichdir)
  1496.       {
  1497.         case DSS_CONF:
  1498.           if (N_ND->CurrentConf)
  1499.           {
  1500.             strcpy(filename,N_ND->CurrentConf->ConfPath);
  1501.           }
  1502.           break;
  1503.         case DSS_NODE:
  1504.           strcpy(filename,N_ND->NodeLocation);
  1505.           break;
  1506.         case DSS_HBBS:
  1507.           strcpy(filename,"HBBS:");
  1508.           break;
  1509.       }
  1510.  
  1511.       if (filename)
  1512.       {
  1513.         if (CurrentAccess<0) TriedAllLevels=TRUE;
  1514.  
  1515.         strcat(filename,DIRNAME_SCREENSSPECIAL);
  1516.         strcat(filename,ScreenName);
  1517.  
  1518.         if (N_ND->User.Valid && !TriedAllLevels)
  1519.         {
  1520.           // add access level _XX here..
  1521.  
  1522.           node=GetNode(BBSGlobal->AcsLevelList,CurrentAccess);
  1523.           CurrentAccess--;
  1524.           strcat(filename,"_");
  1525.           strcat(filename,node->ln_Name);
  1526.         }
  1527.         if (N_ND->User.Valid)
  1528.         {
  1529.           node=GetNode(BBSGlobal->LanguageExtn,N_ND->User.CallData.Language-1); //offset starts at 1
  1530.         }
  1531.         else
  1532.         {
  1533.           node=BBSGlobal->LanguageExtn->lh_Head;
  1534.         }
  1535.         strcat(filename,node->ln_Name);  // *C* Change To Users Selection
  1536.  
  1537.         Done=DisplayScreen(filename);
  1538.  
  1539.       } else TriedAllLevels=TRUE;
  1540.  
  1541.     } while (!TriedAllLevels && !Done);
  1542.  
  1543.  
  1544.     whichdir++;
  1545.  
  1546.   } while (! ((Done) || (whichdir==DSS_ERR)) );
  1547.   return(Done);
  1548. }
  1549.  
  1550. void SaveFileTags( void )
  1551. {
  1552.   struct CfgFileData *cfgfile;
  1553.   char tmpstr[BIG_STR];
  1554.   char optionstr[20];
  1555.   struct TaggedFile *filetagnode;
  1556.   int loop=0;
  1557.  
  1558.   // create unique file name for each user..
  1559.  
  1560.   sprintf(tmpstr,"HBBS:System/Data/TaggedFiles/%d",N_ND->User.CallData.UserID);
  1561.  
  1562.   if (cfgfile=HBBS_CreateConfig(tmpstr))
  1563.   {
  1564.     // this item is ignored, it's just for the sysop's benefit so he can look at a file and see whose tags are in it..
  1565.  
  1566.     HBBS_AddCfgItem(cfgfile,"UserName",N_ND->User.CallData.Handle);
  1567.  
  1568.  
  1569.     for (filetagnode = (struct TaggedFile *)N_ND->TaggedFileList->lh_Head ; filetagnode->node.ln_Succ ; filetagnode =(struct TaggedFile*)filetagnode->node.ln_Succ)
  1570.     {
  1571.       loop++;
  1572.  
  1573.  
  1574.       if (filetagnode=(struct TaggedFile *)GetNode(N_ND->TaggedFileList,loop-1)) // get the node
  1575.       {
  1576.  
  1577.         sprintf(optionstr,"FileName_%d",loop);
  1578.         HBBS_AddCfgItem(cfgfile,optionstr,filetagnode->node.ln_Name);
  1579.  
  1580.         sprintf(optionstr,"WarezFile_%d",loop);
  1581.         HBBS_AddCfgItem(cfgfile,optionstr,filetagnode->WarezFile ? "YES" : "NO");
  1582.  
  1583.         sprintf(optionstr,"ConferenceNum_%d",loop);
  1584.         sprintf(tmpstr,"%d",filetagnode->ConferenceNum);
  1585.         HBBS_AddCfgItem(cfgfile,optionstr,tmpstr);
  1586.  
  1587.         sprintf(optionstr,"FileSize_%d",loop);
  1588.         sprintf(tmpstr,"%d",filetagnode->FileSize);
  1589.         HBBS_AddCfgItem(cfgfile,optionstr,tmpstr);
  1590.       }
  1591.     }
  1592.     HBBS_SaveConfig(cfgfile);
  1593.     HBBS_FlushConfig(cfgfile);
  1594.   }
  1595. }
  1596.  
  1597. void LoadFileTags( void )
  1598. {
  1599.   struct CfgFileData *cfgfile;
  1600.   char tmpstr[BIG_STR];
  1601.   char optionstr[20];
  1602.   char *strptr;
  1603.   struct TaggedFile *filetagnode;
  1604.   BOOL Error=FALSE;
  1605.   N_ND->TaggedFiles=0;
  1606.  
  1607.   // reinitialise list..
  1608.   NewList(N_ND->TaggedFileList);
  1609.  
  1610.   sprintf(tmpstr,"HBBS:System/Data/TaggedFiles/%d",N_ND->User.CallData.UserID);
  1611.  
  1612.   if (cfgfile=HBBS_LoadConfig(tmpstr,LCFG_NONE))
  1613.   {
  1614.     do
  1615.     {
  1616.       Error=TRUE;
  1617.       strptr=NULL;
  1618.  
  1619.       sprintf(optionstr,"FileName_%d",N_ND->TaggedFiles+1);
  1620.       if (HBBS_GetSetting(cfgfile,(void *)&strptr,VTYPE_STRING,optionstr,OPT_SINGLE))
  1621.       {
  1622.         if (filetagnode=AllocVec(sizeof(struct TaggedFile),MEMF_PUBLIC))
  1623.         {
  1624.           N_ND->TaggedFiles++;
  1625.           filetagnode->node.ln_Name=strptr;
  1626.  
  1627.  
  1628.           sprintf(optionstr,"WarezFile_%d",N_ND->TaggedFiles);
  1629.           if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->WarezFile,VTYPE_BOOL,optionstr,OPT_SINGLE))
  1630.           {
  1631.  
  1632.             sprintf(optionstr,"ConferenceNum_%d",N_ND->TaggedFiles);
  1633.             if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->ConferenceNum,VTYPE_BIGNUM,optionstr,OPT_SINGLE))
  1634.             {
  1635.  
  1636.               sprintf(optionstr,"FileSize_%d",N_ND->TaggedFiles);
  1637.               if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->FileSize,VTYPE_BIGNUM,optionstr,OPT_SINGLE))
  1638.               {
  1639.                 Error=FALSE;
  1640.                 AddTail(N_ND->TaggedFileList,(struct Node*) filetagnode);
  1641.               }
  1642.             }
  1643.           }
  1644.           if (Error)
  1645.           {
  1646.             FreeStr(strptr);
  1647.             FreeVec(filetagnode);
  1648.             N_ND->TaggedFiles--;
  1649.           }
  1650.         }
  1651.       }
  1652.     } while (Error==FALSE);
  1653.     HBBS_FlushConfig(cfgfile);
  1654.   }
  1655. }
  1656.  
  1657.  
  1658. void ResetVars( void )
  1659. {
  1660.   LONG loop;
  1661.  
  1662.   for (loop=0;loop<LEN_ACTIONS;loop++)
  1663.   {
  1664.     N_ND->Actions[loop]=ACTC_NONE;
  1665.   }
  1666.   N_ND->Actions[LEN_ACTIONS]=0;
  1667.  
  1668.   N_ND->NodeFlags=NFLG_NONE;
  1669.   N_ND->User.Valid=FALSE;
  1670.   N_ND->Action[0]=0;
  1671.   N_ND->DoorReturn[0]=0;
  1672.   N_ND->CurrentLine[0]=0;
  1673.   N_ND->CurrentLineWrap[0]=0;
  1674.   N_ND->CurrentConf=NULL;
  1675.   N_ND->MaxDIZLines=N_ND->NodeSettings.MaxDIZLines;
  1676.   N_ND->FilesUploaded=0L;
  1677.   N_ND->FilesDownloaded=0L;
  1678.   N_ND->BytesUploaded=0L;
  1679.   N_ND->BytesDownloaded=0L;
  1680.   HBBS_SetBBSCols();
  1681. }
  1682.  
  1683. void FreeData( void )
  1684. {
  1685.   if (N_ND->User.Valid)
  1686.   {
  1687.     HBBS_SaveUserData(&N_ND->User.NormalData);
  1688.     SaveFileTags();
  1689.     FreeFileTags(N_ND);
  1690.   }
  1691.   N_ND->OnlineStatus=OS_OFFLINE;
  1692. }
  1693.  
  1694. void GoBBS( void )
  1695. {
  1696.   char tmpstr[1024],confstr[10],datestr[LEN_DATESTR],timestr[LEN_TIMESTR];
  1697.   V_BIGNUM confnum,loop,loop2;
  1698.   BOOL ReLogin=FALSE;
  1699.  
  1700.   do
  1701.   {
  1702.     ResetVars();
  1703.     PutText(str_CLS);
  1704.     PutText("\033[37;1m");
  1705.  
  1706.     sprintf(tmpstr,"HNode%dLoginType",N_ND->NodeNum);
  1707.  
  1708.     switch(N_ND->LoginType)
  1709.     {
  1710.       case LOGIN_LOCAL:
  1711.         ConWriteStr("-=LOCAL LOGIN=-\r\n");
  1712.         SetVar(tmpstr,"LOCAL",-1 ,GVF_GLOBAL_ONLY);
  1713.         break;
  1714.       case LOGIN_REMOTE:
  1715.         ConWriteStr("-=REMOTE LOGIN=-\r\n");
  1716.         SetVar(tmpstr,"REMOTE",-1 ,GVF_GLOBAL_ONLY);
  1717.         break;
  1718.     }
  1719.  
  1720.     sprintf(tmpstr,"************************************************[%s*", N_ND->LoginType==LOGIN_REMOTE ? "REMOTE]" : "LOCAL]*");
  1721.     HBBS_AddToCallersLog(tmpstr);
  1722.  
  1723.  
  1724.     PutText(ANSI_RESET);
  1725.  
  1726.     GoSystemDoor("FRONTEND",NULL);
  1727.     // ok, check to see what the frontend door returned..
  1728.     strcpy(tmpstr,N_ND->DoorReturn);
  1729.  
  1730.     if (iposition("HACK",tmpstr)>=0)
  1731.     {
  1732.       sprintf(tmpstr,"Hack Attempt - %s",(N_ND->User.Valid ? N_ND->User.CallData.Handle : ""));
  1733.       HBBS_AddToCallersLog(tmpstr);
  1734.  
  1735.       // update list of PW Fails..
  1736.  
  1737.       if (N_ND->User.Valid)
  1738.       {
  1739.         Add_Last_PWFail(N_ND->User.CallData.Handle); // add to both...
  1740.         Add_Last_Caller(N_ND->User.CallData.Handle);
  1741.         N_ND->Actions[ACTN_HACK]=ACTC_HACK;
  1742.       }
  1743.  
  1744.     }
  1745.     else
  1746.     if (iposition("FAILED",tmpstr)>=0)
  1747.     {
  1748.       // do something.. (update calls log)
  1749.  
  1750.       sprintf(tmpstr,"Failed Login - %s",(N_ND->User.Valid ? N_ND->User.CallData.Handle : ""));
  1751.       HBBS_AddToCallersLog(tmpstr);
  1752.     }
  1753.     else
  1754.     if (iposition("LOGGEDIN",tmpstr)>=0)
  1755.     {
  1756.       N_ND->Actions[ACTN_CARRIERLOST]=ACTC_CARRIERLOST; // the LOGOUT door ('G') must set this to ACTC_NONE
  1757.  
  1758.       sprintf(tmpstr,"User logged in, Handle: %s Group: %s Speed: %s",N_ND->User.CallData.Handle,N_ND->User.CallData.Group,N_ND->ConnectBaud);
  1759.       HBBS_AddToCallersLog(tmpstr);
  1760.  
  1761.       HBBS_SetAccess();
  1762.  
  1763.       SetWatchTitles();
  1764.       DOOR_UpdateNodeStatus(UPD_NAME);
  1765.       DOOR_UpdateNodeStatus(UPD_GROUP);
  1766.       Add_Last_Caller(N_ND->User.CallData.Handle);
  1767.  
  1768.       // update the users stats..
  1769.  
  1770.       N_ND->User.NormalData.CallsMade++;
  1771.       N_ND->User.CallData.CallsMade++;
  1772.       time(&N_ND->User.CallData.LastCalledDate);
  1773.       N_ND->User.NormalData.LastCalledDate=N_ND->User.CallData.LastCalledDate;
  1774.  
  1775.       // user logged in ok.
  1776.       sprintf(tmpstr,"HNode%dUser",N_ND->NodeNum);
  1777.       SetVar(tmpstr,N_ND->User.CallData.Handle,-1,GVF_GLOBAL_ONLY);
  1778.       LoadFileTags();
  1779.  
  1780.       HBBS_GetDate(datestr);
  1781.       HBBS_GetTime(timestr);
  1782.  
  1783.       if (stricmp(BBSGlobal->LastCalledDate,datestr)==0)
  1784.       {
  1785.         BBSGlobal->CallsToday++;
  1786.         N_ND->CallsToday++;
  1787.       }
  1788.       else
  1789.       {
  1790.         BBSGlobal->CallsToday=1;
  1791.         N_ND->CallsToday=1;
  1792.       }
  1793.  
  1794.       strcpy(BBSGlobal->LastCalledDate,datestr);
  1795.       strcpy(BBSGlobal->LastCalledTime,timestr);
  1796.  
  1797.       strcpy(N_ND->LastCalledDate,datestr);
  1798.       strcpy(N_ND->LastCalledTime,timestr);
  1799.  
  1800.       HBBS_SaveCallsData();
  1801.  
  1802.  
  1803.       UpdateInfoWin(); // updates calls number in the window...
  1804.  
  1805.       GoSystemDoor("CheckUser","LOGON");
  1806.  
  1807.       if (stricmp(N_ND->DoorReturn,"LOGIN_DENIED")==0)
  1808.       {
  1809.       }
  1810.       else
  1811.       {
  1812.         sprintf(tmpstr,"Speed_%s",N_ND->ConnectBaud);
  1813.         GoSystemDoor(tmpstr,NULL);
  1814.  
  1815.         if (N_ND->OnlineStatus==OS_ONLINE)
  1816.         {
  1817.  
  1818.           if (N_ND->User.CallData.Status!=USER_NEW)
  1819.           {
  1820.             DisplaySpecialScreen("LoginLogo");
  1821.           }
  1822.  
  1823.           if (N_ND->OnlineStatus==OS_ONLINE)
  1824.           {
  1825.  
  1826.             GoUserDoor("WALL",NULL);
  1827.  
  1828.             DisplaySpecialScreen("Bulletin");
  1829.  
  1830.             // check to see if user want's to keep tagged files from last visit
  1831.             // if he left with tagged files or lost carrier with files still tagged
  1832.  
  1833.             GoSystemDoor("CHECKTAGS",NULL);
  1834.  
  1835.             GoSystemDoor("MAILSCAN",NULL);
  1836.  
  1837.  
  1838.             sprintf(tmpstr,"HBBS:Screens/Users/%s.TXT",N_ND->User.CallData.Handle);
  1839.             DisplayScreen(tmpstr);  // *C* keep ?
  1840.  
  1841.             confnum=N_ND->User.CallData.LastConf;
  1842.             if (N_ND->User.CallData.PreferedConf) confnum=N_ND->User.CallData.PreferedConf;
  1843.             sprintf(confstr,"%d",confnum);
  1844.             GoSystemDoor("JOINCONF",confstr);
  1845.  
  1846.  
  1847.             GoSystemDoor("CMDPROMPT",NULL);
  1848.  
  1849.             // Normally a user is only logged off a) by the sysop pressing F10 or b) by
  1850.             // typing G at the CMDPROMPT door which then calls the logoff door. but if
  1851.             // there is a problem with starting the CMDPROMPT door then we'll have to force
  1852.             // logout the user by trying to run the LOGOUT door, which should logoff the
  1853.             // user
  1854.  
  1855.             if (N_ND->OnlineStatus==OS_ONLINE)
  1856.             {
  1857.               GoUserDoor("G","SYSTEM");
  1858.             }
  1859.           }
  1860.         }
  1861.       }
  1862.  
  1863.       // do the logoff scripts, but only if a user actually logged in..
  1864.       // and unlike /X this gets called even if you do a RL
  1865.       // so all your bulletins actually get updated!
  1866.  
  1867.       sprintf(tmpstr,"execute HBBS:Scripts/LogOff%ld.script %ld %ld",N_ND->NodeNum,N_ND->NodeNum,N_ND->User.CallData.UserID);
  1868.       HBBS_RunDOSCMD(tmpstr,FALSE);
  1869.  
  1870.       sprintf(tmpstr,"execute HBBS:Scripts/LogOff_Global.script %ld %ld",N_ND->NodeNum,N_ND->User.CallData.UserID);
  1871.       HBBS_RunDOSCMD(tmpstr,FALSE);
  1872.  
  1873.     }
  1874.  
  1875.     strcpy(tmpstr,"Actions: ");
  1876.     loop2=strlen(tmpstr);;
  1877.     for (loop=0;loop<LEN_ACTIONS;loop++)
  1878.     {
  1879.       if (N_ND->Actions[loop]!=ACTC_NONE)
  1880.       {
  1881.         tmpstr[loop2++]=N_ND->Actions[loop];
  1882.       }
  1883.     }
  1884.     tmpstr[loop2]=0;
  1885.     HBBS_AddToCallersLog(tmpstr);
  1886.  
  1887.     HBBS_AddToCallersLog("End Of Session");
  1888.  
  1889.  
  1890.     FreeData();
  1891.     if (stricmp(N_ND->DoorReturn,"RELOGIN")==0)
  1892.     {
  1893.       ReLogin=TRUE;
  1894.       N_ND->OnlineStatus=OS_ONLINE;
  1895.       HBBS_AddToCallersLog("User is re-logging in!");
  1896.     }
  1897.     else
  1898.     {
  1899.       ReLogin=FALSE;
  1900.     }
  1901.  
  1902.   } while(ReLogin);
  1903.  
  1904.   HangUp();
  1905. }
  1906.  
  1907. void ResetNodeVars( void )
  1908. {
  1909.   ResetVars();
  1910.   // this is called just before the await connect door is called..
  1911.   strcpy(N_ND->ConnectBaud,"--------");
  1912.   DOOR_UpdateNodeStatus(UPD_ACTION);
  1913.   DOOR_UpdateNodeStatus(UPD_CPSBAUD);
  1914.   HBBS_SetAccess(); // clear access levels
  1915. }
  1916.  
  1917. BOOL CheckModem( void )
  1918. {
  1919.   BOOL retval=TRUE,Done=FALSE;
  1920.   if (N_ND->SerOK)
  1921.   {
  1922.     do
  1923.     {
  1924.       SerReset();
  1925.       if (SerWriteStrWithTimeout("AT\n\r",5,0))
  1926.       {
  1927.         Delay(N_ND->NodeDevice.DelayBetweenCmds);
  1928.         Done=TRUE;
  1929.       }
  1930.       else
  1931.       {
  1932.         Done=((rtEZRequest("Modem Not Responding","Retry|Cancel",NULL,(struct TagItem *)&rttags,NULL)) ? FALSE : TRUE);
  1933.         if (Done) retval=FALSE;
  1934.       }
  1935.       SerReset();
  1936.     } while (!Done);
  1937.   }
  1938.   return(retval);
  1939. }
  1940.  
  1941. void AwaitConnect( void )
  1942. {
  1943.   BOOL Error=FALSE;
  1944.  
  1945.   ResetNodeVars();
  1946.  
  1947.   if (((N_ND->NodeDevice.NullModemCable==FALSE) && CheckModem()) || (N_ND->NodeDevice.NullModemCable==TRUE))
  1948.   {
  1949.     do
  1950.     {
  1951.       if (!N_ND->NodeDevice.NullModemCable) InitModem();
  1952.       Error=!GoSystemDoor("AWAIT",NULL);                 // GoSys returns true if door loads OK
  1953.  
  1954.       // if local login then put modem offhook so no-one else calls...
  1955.       if (N_ND->LoginType==LOGIN_LOCAL)
  1956.       {
  1957.         if (!N_ND->NodeDevice.NullModemCable) OffHook();
  1958.         strcpy(N_ND->ConnectBaud,"LOCAL");
  1959.       }
  1960.  
  1961.       DOOR_UpdateNodeStatus(UPD_CPSBAUD);
  1962.       if (N_ND->LoginType!=LOGIN_NONE)
  1963.       {
  1964.         if (HistoryList=HBBS_CreateList())
  1965.         {
  1966.           HistoryItems=0;
  1967.  
  1968.           SendStatus(STAT_ONLINE);
  1969.           N_ND->OnlineStatus=OS_ONLINE;
  1970.  
  1971.           GoBBS();
  1972.  
  1973.           N_ND->LoginType=LOGIN_NONE;
  1974.  
  1975.           FreeStrList(HistoryList);
  1976.           HistoryList=NULL;
  1977.           HistoryItems=0;
  1978.  
  1979.           HBBS_FreeListNodes(N_ND->OLMList);
  1980.           N_ND->OLMCount=0;
  1981.  
  1982.           if (N_ND->NodeFlags & NFLG_OLMSWAITING) N_ND->NodeFlags-=NFLG_OLMSWAITING;
  1983.  
  1984.           SendStatus(STAT_READY);
  1985.         }
  1986.  
  1987.       }
  1988.       ResetNodeVars();
  1989.     } while (N_ND->RequestShutdown==FALSE && !Error);
  1990.     if (!N_ND->NodeDevice.NullModemCable) OffHook();
  1991.   } // else do error message
  1992.   if (Error)
  1993.   {
  1994.     HBBS_rterror("Error running door, \"Await\"");
  1995.   }
  1996. }
  1997.  
  1998. void HandleDoorIOMsg(struct DoorIOMsg *DMsg)
  1999. {
  2000.   DMsg->ReturnVal=0;
  2001.   switch(DMsg->Status)
  2002.   {
  2003.     case DOORIO_WRITECONSTR:
  2004.       ConWriteStr(DMsg->Data);
  2005.       break;
  2006.     case DOORIO_WRITECONDATA:
  2007.       ConWriteData(DMsg->Data,DMsg->DataLength);
  2008.       break;
  2009.     case DOORIO_WRITESERSTR:
  2010.       SerWriteStr(DMsg->Data);
  2011.       break;
  2012.     case DOORIO_WRITESERDATA:
  2013.       SerWriteData(DMsg->Data,DMsg->DataLength);
  2014.       break;
  2015.     case DOORIO_WRITESTR:
  2016.       PutText(DMsg->Data);
  2017.       break;
  2018.     case DOORIO_GETLINE:
  2019.       DMsg->ReturnVal=Get_Line(DMsg->Flags,DMsg->Data[0],DMsg->Num1,DMsg->Num2,DMsg->OptionStr);
  2020.       break;
  2021.     case DOORIO_SYSTEMDOOR:
  2022.       DMsg->ReturnVal=GoSystemDoor(DMsg->Data,DMsg->OptionStr);
  2023.       break;
  2024.     case DOORIO_USERDOOR:
  2025.       DMsg->ReturnVal=GoUserDoor(DMsg->Data,DMsg->OptionStr);
  2026.       break;
  2027.     case DOORIO_HANGUP:
  2028.       HangUp();
  2029.       break;
  2030.     case DOORIO_DISPLAYSCREEN:
  2031.       DMsg->ReturnVal=DisplayScreen(DMsg->Data);
  2032.       break;
  2033.     case DOORIO_DISPLAYSPECIALSCREEN:
  2034.       DMsg->ReturnVal=DisplaySpecialScreen(DMsg->Data);
  2035.       break;
  2036.     case DOORIO_PAUSEPROMPT:
  2037.       PausePrompt(DMsg->Data,0);
  2038.       break;
  2039.     case DOORIO_CONTINUEPROMPT:
  2040.       DMsg->ReturnVal=ContinuePrompt(DMsg->Data,DMsg->Flags);
  2041.       break;
  2042.     case DOORIO_ADDLASTUPLOAD:
  2043.       Add_Last_Upload(DMsg->Data);
  2044.       break;
  2045.     case DOORIO_MENUPROMPT:
  2046.       MenuPrompt(DMsg->Data,DMsg->OptionStr[0]);
  2047.       break;
  2048.   }
  2049.   // a door message MAY be sent to the node without the control or other program
  2050.   // wanting to be told that the NODE has recived the message, all messages sent
  2051.   // that DONT want a reply WILL be freed..
  2052.  
  2053.   if (DMsg->message.mn_ReplyPort)
  2054.   {
  2055.     ReplyMsg((struct Message *)DMsg);
  2056.   }
  2057.   else
  2058.   {
  2059.     FreeVec(DMsg);
  2060.   }
  2061. }
  2062.  
  2063.